package com.ihome.android.util;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import android.app.Activity;
import android.app.WallpaperManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageStatsObserver;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.PaintDrawable;
import android.text.TextUtils;
import android.util.Log;

import com.ihome.android.common.ConfigUtil;
import com.ihome.android.image.util.Version;
import com.ihome.android.market2.info.AppInfo;
import com.ihome.android.util.log.LogUtil;

/**
 * All kinds of operation method of App
 * 
 * @author Emerson
 * 
 */
public class AppMgr {
	private static final String	TAG				= AppMgr.class.getSimpleName();
	public final static String	SETTINGSPKGNAME	= "com.android.settings";
	public static boolean		mWallpaperChecked;
	private static AppMgr		mAppMgr			= null;

	public static AppMgr getInstance() {
		if (null == mAppMgr) {
			mAppMgr = new AppMgr();
		}
		return mAppMgr;
	}

	/**
	 * When no wallpaper was manually set, a default wallpaper is used instead.
	 */
	public void setDefaultWallpaper(Activity mActivity) {
		Log.d(TAG, "In setDefaultWallpaper()");
		if (!mWallpaperChecked) {
			WallpaperManager manager = WallpaperManager.getInstance(mActivity);
			Drawable wallpaper = manager.peekDrawable();
			if (wallpaper == null) {
				try {
					manager.clear();
				} catch (IOException e) {
					Log.e(TAG, "Failed to clear wallpaper " + e);
				}
			}
			else {
				Log.d(TAG, "Setting wallpaper");
				mActivity.getWindow().setBackgroundDrawable(wallpaper);
			}
			mWallpaperChecked = true;
		}
	}

	public AppInfo getApplicationInfo(PackageManager manager, Intent intent) {
		final ResolveInfo resolveInfo = manager.resolveActivity(intent, 0);

		if (resolveInfo == null) {
			return null;
		}

		final AppInfo info = new AppInfo();
		final ActivityInfo activityInfo = resolveInfo.activityInfo;
		info.icon = activityInfo.loadIcon(manager);
		if (info.getAppName() == null || info.getAppName().length() == 0) {
			info.setAppName(activityInfo.loadLabel(manager).toString());
		}
		if (info.getAppName() == null) {
			info.setAppName("");
		}
		return info;
	}

	/**
	 * Loads the application by package name.
	 */
	public AppInfo loadAppByPkgName(Context mContext, String pkgName) {
		AppInfo appInfo = new AppInfo();
		if (TextUtils.isEmpty(pkgName)) {
			return null;
		};

//		Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
//		mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
//		PackageManager manager = mContext.getPackageManager();
//		final List<ResolveInfo> apps = manager.queryIntentActivities(mainIntent, 0);
//		Collections.sort(apps, new ResolveInfo.DisplayNameComparator(manager));
//
//		if (apps != null) {
//			final int count = apps.size();
//
//			ResolveInfo settingsInfo = null;
//			for (int i = 0; i < count; i++) {
//				ResolveInfo info = apps.get(i);
//
//				if (info.activityInfo.applicationInfo.packageName.equals(pkgName)) {
//					LogUtil.v(TAG, "App Name : " + info.loadLabel(manager) + "; pkgName = " + info.activityInfo.applicationInfo.packageName);
//
//					appInfo.setAppName(info.loadLabel(manager).toString());
//					appInfo.setPkgName(info.activityInfo.applicationInfo.packageName);
//					appInfo.icon = info.activityInfo.loadIcon(manager);
//					return appInfo;
//
//				}
//
//			}
//		}
		
		PackageManager manager = mContext.getPackageManager();
		List<PackageInfo> packageInfoList = manager.getInstalledPackages(0); //返回已安装的包信息列表  
		if (packageInfoList != null) {
			for (PackageInfo packageInfo : packageInfoList) {
				if (packageInfo.packageName.equals(pkgName)) {
					appInfo.setAppName(packageInfo.applicationInfo.loadLabel(manager).toString());
					appInfo.setPkgName(packageInfo.packageName);
					appInfo.setVersion(packageInfo.versionName);
					appInfo.icon = packageInfo.applicationInfo.loadIcon(manager);
				}
			}
		}

		return appInfo;
	}

	/**
	 * Loads the list of User installed applications in mApplications.
	 */
	public ArrayList<AppInfo> loadDataApps(Context mContext) {
		ArrayList<AppInfo> mApplications = null;
		PackageManager manager = mContext.getPackageManager();

		List<PackageInfo> packageInfoList = manager.getInstalledPackages(0); //返回已安装的包信息列表  

		if (packageInfoList != null) {

			if (mApplications == null) {
				mApplications = new ArrayList<AppInfo>();
			}
			mApplications.clear();

			for (PackageInfo packageInfo : packageInfoList) {
				if(packageInfo.packageName.equals(ConfigUtil.CTC_ZHIHUI_KEY) || packageInfo.packageName.equals(ConfigUtil.MEDIARENDER_KEY)){
					continue;
				}
				/* 
				 * 判断是否为非系统应用 
				 * */
				if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
					AppInfo app = new AppInfo();

					app.setAppName(packageInfo.applicationInfo.loadLabel(manager).toString());
					app.setPkgName(packageInfo.packageName);
					app.setVersion(packageInfo.versionName);
					app.icon = packageInfo.applicationInfo.loadIcon(manager);

					mApplications.add(app);
				}
			}
		}

		return mApplications;
	}

	/**
	 * Loads the list of installed applications in mApplications.
	 */
	public ArrayList<AppInfo> loadApplications(Context mContext) {
		ArrayList<AppInfo> mApplications = null;
		PackageManager manager = mContext.getPackageManager();

		Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
		mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);

		final List<ResolveInfo> apps = manager.queryIntentActivities(mainIntent, 0);
		Collections.sort(apps, new ResolveInfo.DisplayNameComparator(manager));

		if (apps != null) {
			final int count = apps.size();

			if (mApplications == null) {
				mApplications = new ArrayList<AppInfo>(count);
			}
			mApplications.clear();

			for (int i = 0; i < count; i++) {
				AppInfo app = new AppInfo();
				ResolveInfo info = apps.get(i);
				LogUtil.v(TAG, "-------App Name : " + info.loadLabel(manager) + "; pkgName = " + info.activityInfo.applicationInfo.packageName);
				app.setAppName(info.loadLabel(manager).toString());
				app.setPkgName(info.activityInfo.applicationInfo.packageName);
				app.icon = info.activityInfo.loadIcon(manager);

				mApplications.add(app);
			}
		}

		return mApplications;
	}

	public Drawable resizedAppIcon(Drawable icon, int width, int height) {
		Rect mOldBounds = new Rect();
		// final Resources resources = getContext().getResources();
		if (width == 0)
			width = 80;// (int)
						// resources.getDimension(android.R.dimen.app_icon_size);
		if (height == 0)
			height = 80; // (int)
							// resources.getDimension(android.R.dimen.app_icon_size);

		final int iconWidth = icon.getIntrinsicWidth();
		final int iconHeight = icon.getIntrinsicHeight();

		if (icon instanceof PaintDrawable) {
			PaintDrawable painter = (PaintDrawable) icon;
			painter.setIntrinsicWidth(width);
			painter.setIntrinsicHeight(height);
		}

		// if (width > 0 && height > 0 && (width < iconWidth || height <
		// iconHeight)) {
		final float ratio = (float) iconWidth / iconHeight;

		if (iconWidth > iconHeight) {
			height = (int) (width / ratio);
		}
		else if (iconHeight > iconWidth) {
			width = (int) (height * ratio);
		}

		final Bitmap.Config c = icon.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
		final Bitmap thumb = Bitmap.createBitmap(width, height, c);
		final Canvas canvas = new Canvas(thumb);
		canvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.DITHER_FLAG, 0));
		// Copy the old bounds to restore them later
		// If we were to do oldBounds = icon.getBounds(),
		// the call to setBounds() that follows would
		// change the same instance and we would lose the
		// old bounds
		mOldBounds.set(icon.getBounds());
		icon.setBounds(0, 0, width, height);
		icon.draw(canvas);
		icon.setBounds(mOldBounds);
		icon = new BitmapDrawable(thumb);
		return icon;
	}

	/**
	 * 
	 * 获取应用的大小，包括cachesize 缓存大小 codesize 应用程序大小 datasize 数据大小
	 * 
	 * @param context
	 * @param appinfo
	 * @param pkgSizeObserver
	 *            -- 每次调用需要New一个新的PkgSizeObserver 对象，并传入之前的AppInfo
	 * @throws Exception
	 */
	public static void queryPkgSize(Context context, AppInfo appinfo, PkgSizeObserver pkgSizeObserver) throws Exception {
		if (appinfo.getPkgName() != null) {
			//使用放射机制得到PackageManager类的隐藏函数getPackageSizeInfo
			PackageManager pm = context.getPackageManager();
			try {

				// 4.2 以上
				if (Version.hasJellyBean()) {
					Method getPackageSizeInfo = pm.getClass().getDeclaredMethod("getPackageSizeInfo", String.class, int.class, IPackageStatsObserver.class);
					/**
					 * after invoking, PkgSizeObserver.onGetStatsCompleted() will be
					 * called as callback function. <br>
					 * About the third parameter ‘Process.myUid() / 100000’，please
					 * check:
					 * <android_source>/frameworks/base/core/java/android/content
					 * /pm/PackageManager.java: getPackageSizeInfo(packageName,
					 * UserHandle.myUserId(), observer);
					 */
					getPackageSizeInfo.invoke(pm, appinfo.getPkgName(), appinfo.getUid() / 100000, pkgSizeObserver);
				}else{
					//通过反射机制获得该隐藏函数  
					Method getPackageSizeInfo = pm.getClass().getDeclaredMethod("getPackageSizeInfo", String.class,IPackageStatsObserver.class);
					//调用该函数，并且给其分配参数 ，待调用流程完成后会回调PkgSizeObserver类的函数  
					getPackageSizeInfo.invoke(pm, appinfo.getPkgName() , pkgSizeObserver);  
				}
				
			} catch (Exception ex) {
				Log.e(TAG, "NoSuchMethodException");
				ex.printStackTrace();
			}
		}
	}

}
